package ProtocolInfoFile;
import java.math.BigInteger;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import java.io.File;


/**
 * 
 * @author Hadar Miller
 *
 */

public class ProtocolInfoFile {
	
	private String version;
	private String sid;
	private int k;
	private int lambda;
	private int ne;
	private int nr;
	private int nv;
	private String sHash;
	private String sPRG;
	private String sGroup;
	private int wDefault;
	
	
	public ProtocolInfoFile(String version, String sid, int k, int lambda, int ne, int nr, int nv, String sHash, String sPRG, String sGroup, int wDefault)
	{
		this.version = version;
		this.sid = sid;
		this.k = k;
		this.lambda = lambda;
		this.ne = ne;
		this.nr = nr;
		this.nv = nv;
		this.sHash = sHash;
		this.sPRG = sPRG;
		this.sGroup = sGroup;
		this.wDefault = wDefault;
	}
	
	/**
	 * 
	 * @return string representing the version. 
	 */
	public String getVersion() {
		return version;
	}
	
	/**
	 * 
	 * @return 
	 */
	public String getSid() {
		return sid;
	}
	
	/**
	 * 
	 * @return The number of parties that participate.
	 */
	public int getK() {
		return k;
	}
	
	/**
	 * 
	 * @return The number of parties that must be corrupted to break the privacy of the senders.
	 */
	public int getLambda() {
		return lambda;
	}
	
	/**
	 * 
	 * @return The number of bits in each component of random vectors used for batching in proofs of shuffles and proofs of correct decryption.
	 */
	public int getNe() {
		return ne;
	}
	
	/**
	 * 
	 * @return The acceptable statistical error when sampling random values, randomly chosen element in the protocol are chosen with as distribution at distance of at most 2^(-ret_val) from uniform distribution.
	 */
	public int getNr() {
		return nr;
	}
	
	/**
	 * 
	 * @return The number of bits used in the challenge of the verifier in zero- knowledge proofs.
	 */
	public int getNv() {
		return nv;
	}
	
	/**
	 * 
	 * @return The string representing the name of hash function.
	 */
	public String getSHash() {
		return sHash;
	}
	
	/**
	 * 
	 * @return The string representing the name of hash function to send to the prg.
	 */
	public String getSPRG() {
		return sPRG;
	}
	
	/**
	 * 
	 * @return The string representing the marshalled group.
	 */
	public String getSGroup() {
		return sGroup;
	}
	
	/**
	 * 
	 * @return The default width.
	 */
	public int getWDefault() {
		return wDefault;
	}
	
	/**
	 * Parse xml file and extract the values parameter.
	 * @param xmlPath path to the xml file.
	 * @return ProtocolInfoFile object which contains all the parameters from the xml file.
	 * @throws Exception if one or more of the parameters are missing.
	 */
	public static ProtocolInfoFile parse(String xmlPath) throws Exception {
		String version = null;
		String sid = null;
		int k = 0;
		int lambda = 0;
		int ne = 0;
		int nr = 0;
		int nv = 0;
		String sHash = null;
		String sPRG = null;
		String sGroup = null;
		int wDefault = 0;
		
		  try {
			  
				File fXmlFile = new File(xmlPath);
				DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
				DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
				Document doc = dBuilder.parse(fXmlFile);
				doc.getDocumentElement().normalize();
				
				NodeList nList = doc.getElementsByTagName("protocol");
		 
		 
				   Node nNode = nList.item(0);
				   
				   if (nNode.getNodeType() == Node.ELEMENT_NODE) {
		 
				      Element eElement = (Element) nNode;
				      version = getTagValue("version", eElement);
				      sid = getTagValue("sid", eElement);
				      k = Integer.parseInt(getTagValue("nopart", eElement));
				      lambda = Integer.parseInt(getTagValue("thres", eElement));
				      ne = Integer.parseInt(getTagValue("vbitlenro", eElement));
				      nr = Integer.parseInt(getTagValue("statdist", eElement));
				      nv = Integer.parseInt(getTagValue("cbitlenro", eElement));
				     /* isn't it suppose to be the same hash? */
				      sHash = getTagValue("rohash", eElement);
				      sPRG = getTagValue("prg", eElement);
				      sGroup = getTagValue("pgroup", eElement);
				      wDefault = Integer.parseInt(getTagValue("width", eElement));
				
				   }
				   
			  } catch (Exception e) {
				  throw new Exception("A problem occure while parsing the XML file:\n" + e.getMessage());
			  }
			  
		  
		  return new ProtocolInfoFile(version, sid, k, lambda, ne, nr, nv, sHash, sPRG, sGroup, wDefault);
		  }
		 
		  private static String getTagValue(String sTag, Element eElement) throws Exception {
			NodeList nlList = eElement.getElementsByTagName(sTag).item(0).getChildNodes();

		
	        Node nValue = (Node) nlList.item(0);
			   if (nValue == null) {
				   return "";
			   }
			   else 
				   return nValue.getNodeValue();
			 
		  }

}
